package common.security.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Service;

import common.hibernate.service.impl.BaseServiceImpl;
import common.rbac.po.Authority;
import common.rbac.po.Group;
import common.rbac.po.Role;
import common.rbac.po.User;
import common.security.Constant;
import common.security.service.UserService;


@Service
public class UserServiceImpl extends BaseServiceImpl implements UserService {

	
	@Override
	public User findUserAndAllAuthority(String username, Set<GrantedAuthority> authSet) {
		String hql = "from User where name=? and enabled = ?";
		User user = (User) this.findOne(hql, username, true);
		if (null != user) {
			Set<Group> groups = getGroups(user);
			Set<Role> roles = new HashSet<Role>(this.find("select r from Role r, UserRole ur where r.id = ur.roleId and ur.userId = ?", user.getId()));
			Set<Authority> auths = new HashSet<Authority>();
			
			List<Object> groupIds = new ArrayList<>();
			for (Group group : groups) {
				authSet.add(new SimpleGrantedAuthority(Constant.GROUP_PREFIX + group.getGroup()));
				groupIds.add(group.getId());
			}
			if (groupIds.size() > 0) {
				// 增加上级部门的角色
				roles.addAll(this.findByParamList("select r from Role r, GroupRole gr where r.id = gr.roleId and gr.groupId in :list", groupIds, new Object[0]));
			}
			// 用户包含的所有角色
			List<Object> roleIds = new ArrayList<>();
			for (Role role : roles) {
				authSet.add(new SimpleGrantedAuthority(Constant.ROLE_PREFIX + role.getRole()));
				roleIds.add(role.getId());
			}
			if (roleIds.size() > 0) {
				auths.addAll(this.findByParamList("select a from Authority a, RoleAuthority ra where a.id = ra.authId and ra.roleId in :list", roleIds, new Object[0]));
			}
			
			for (Authority auth : auths) {
				authSet.add(new SimpleGrantedAuthority(Constant.AUTH_PREFIX + auth.getAuthority()));
				addAuthority(auths,  auth);
				
				Authority parent = this.findOne("from Authority where parentId = ?", auth.getId());
				while(null != parent) {
					authSet.add(new SimpleGrantedAuthority(Constant.AUTH_PREFIX + parent.getAuthority()));
					addAuthority(auths, parent);
					parent = this.findOne("from Authority where parentId = ?", parent.getId());
				}
			}
		}
		return user;
	}


	/**
	 * 获取用户的所有上级部门
	 * @param userId
	 * @return
	 */
	protected Set<Group> getGroupsForUserId(String userId) {
		Set<Group> groups = new HashSet<Group>(this.find("select g from Group g, UserGroup ug where g.id = ug.groupId and ug.userId = ?", userId));
		for (Group group : groups) {
			iterabe(group, groups);
		}
		return groups;
	}
	
	public Set<Group> getGroups(User user) {
		return getGroupsForUserId(user.getId());
	}
	
	public Set<Group> getGroups(String userId) {
		return getGroupsForUserId(userId);
	}

	
	private void iterabe(Group group, Set<Group> groups) {
		if(StringUtils.isNotBlank(group.getParentId())) {
			Group findOne = this.findOne("from Group where parentId = ?", group.getId());
			iterabe(findOne, groups);
		} else {
			groups.add(group);
		}
	}


	private void addAuthority(Set<Authority> auths, Authority auth) {
		Calendar current = GregorianCalendar.getInstance();
		//判断权限是否过期
		if(null ==auth.getExpiredDt() || current.getTime().before(auth.getExpiredDt())) {
			auths.add(auth);
		}
		//设置禁止访问的权限
	}
}
